
%% Copyright (c) 2006 Christophe Romain <cromain@process-one.net>
%%
%% Permission is hereby granted, free of charge, to any person
%% obtaining a copy of this software and associated documentation
%% files (the "Software"), to deal in the Software without restriction,
%% including without limitation the rights to use, copy, modify, merge,
%% publish, distribute, sublicense, and/or sell copies of the Software,
%% and to permit persons to whom the Software is furnished to do
%% so, subject to the following conditions:
%%
%% The above copyright notice and this permission notice shall be included
%% in all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
%% IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
%% CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
%% TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
%% SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

%% @doc The ErlyDB ODBC driver.

-module(erlydb_odbc).
-author('christophe.romain@process-one.net').

-export([
	connect/5,
	import/0,
	export/0,
	select/3,
	insert/2,
	update/3,
	delete/2,
	count/2,
	max/3,
	nextid/1,
	size/1,
	sql/1 ]).

%% @doc Initialize ODBC connection.
connect(Hostname, _Username, _Password, _Database, _Options) ->
	case odbc:connect(Hostname, [{scrollable_cursor, off}]) of
	{ok, Ref} ->
		erlang:monitor(process, Ref),
		{ok, [Ref]};
	{error, _Reason} ->
		{stop, odbc_connection_failed}
	end.
	
%% @doc XML data import function
import() ->
	not_implemented.

%% @doc XML data export export function
export() ->
	not_implemented.

%%%%%%%%%%%
%% Helpers

data_to_list(Atom) when is_atom(Atom) ->
	atom_to_list(Atom);
data_to_list(Values) when is_list(Values) ->
	{[K1|KT], [V1|VT]} = lists:unzip(Values),
	KS = io_lib:format("(~p", [K1]),
	VS = io_lib:format("(~p", [V1]),
	lists:foldl(fun(Elem, AccIn) ->
		AccIn ++ io_lib:format(",~p", [Elem])
	end, KS, KT) ++ ") VALUES " ++
	lists:foldl(fun(Elem, AccIn) ->
		AccIn ++ io_lib:format(",~p", [Elem])
	end, VS, VT) ++ ")";
data_to_list({Field, Op, Value}) ->
	io_lib:format("~s~s~p", [Field, Op, Value]);
data_to_list({Field, Value}) ->
	io_lib:format("~s=~p", [Field, Value]);
data_to_list(Undefined) ->
	io_lib:format("~p", [Undefined]).
data_to_list(_Delim, []) ->
	"*";
data_to_list(Delim, Data) ->
	data_to_list(Delim, Data, []).
data_to_list(Delim, [Field|Tail], []) ->
	NewList = [data_to_list(Field)],
	data_to_list(Delim, Tail, NewList);
data_to_list(Delim, [Field|Tail], List) ->
	NewList = [data_to_list(Field), Delim | List],
	data_to_list(Delim, Tail, NewList);
data_to_list(_, [], List) ->
	lists:flatten(lists:reverse(List)).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ErlyDB Database Actions

%% note for Yariv:
%%  this is not working
%%  still did not get enough time to work on

select(Table, Fields, Where) ->
	sql(["SELECT ", data_to_list(",", Fields),
	     " FROM ", data_to_list(Table),
	     " WHERE ", data_to_list(" AND ", Where)]).

insert(Table, Values) ->
	sql(["INSERT INTO ", data_to_list(Table), data_to_list(Values)]).

update(Table, Values, Where) ->
	sql(["UPDATE ", data_to_list(Table),
	     " SET ", data_to_list(",", Values),
	     " WHERE ", data_to_list(" AND ", Where)]).

delete(Table, Where) ->
	sql(["DELETE FROM ", data_to_list(Table),
	     " WHERE ", data_to_list(" AND ", Where)]).

count(Table, Where) -> 
	sql(["SELECT COUNT * FROM ", data_to_list(Table),
	     " WHERE ", data_to_list(" AND ", Where)]).

max(_Table, _Field, _Where) -> 
	ok.

nextid(_Table) -> 
	ok.

size(Table) ->
	sql(["SELECT table_rows",
	     " FROM information_schema.tables",
	     " WHERE table_name='", Table, "'"]).

sql(SqlQuery) ->
	%Ref = get_from_context,
	%odbc:sql_query(Ref, SqlQuery).
	io:format("sql: ~s;~n", [SqlQuery]).
